package top.huhuiyu.springboot3.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.huhuiyu.springboot3.base.R;
import top.huhuiyu.springboot3.entity.user.AuthInfo;
import top.huhuiyu.springboot3.entity.user.TbAction;
import top.huhuiyu.springboot3.entity.user.TbRoleAction;
import top.huhuiyu.springboot3.entity.user.TbUser;
import top.huhuiyu.springboot3.interceptor.AppInterceptor;
import top.huhuiyu.springboot3.mapper.TbActionMapper;
import top.huhuiyu.springboot3.mapper.TbRoleActionMapper;
import top.huhuiyu.springboot3.mapper.TbUserMapper;
import top.huhuiyu.springboot3.service.AuthService;
import top.huhuiyu.springboot3.service.RedisService;
import top.huhuiyu.springboot3.util.EncryptorUtils;
import top.huhuiyu.springboot3.vo.UserAuth;
import top.huhuiyu.springboot3.vo.UserPwd;

import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class AuthServiceImpl implements AuthService {
    private final TbUserMapper tbUserMapper;
    private final TbActionMapper tbActionMapper;
    private final TbRoleActionMapper tbRoleActionMapper;
    private final RedisService redisService;

    @Override
    public R<String> updatePwd(UserPwd user) {
        // 认证信息
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        String token = authInfo.getToken();
        Integer id = authInfo.getId();
        TbUser u = tbUserMapper.selectById(id);
        // 校验密码，需要加密后比对
        String pwd = EncryptorUtils.saltMd5(user.getOldPwd(), u.getSalt());
        if (!u.getPassword().equals(pwd)) {
            return R.fail("密码错误", null);
        }
        // 修改密码
        u.setPassword(EncryptorUtils.saltMd5(user.getNewPwd(), u.getSalt()));
        tbUserMapper.updateById(u);
        return R.ok("密码修改成功", null);
    }

    @Override
    public R<String> reg(UserAuth user) {
        TbUser check = queryByName(user.getUsername());
        if (check != null) {
            return R.fail("用户已存在", null);
        }
        String salt = EncryptorUtils.randString(6);
        check = new TbUser();
        check.setSalt(salt);
        check.setUsername(user.getUsername());
        check.setPassword(EncryptorUtils.saltMd5(user.getPassword(), salt));
        check.setRole(2);
        tbUserMapper.insert(check);
        return R.ok("注册成功", null);
    }


    @Override
    public boolean checkAuth() {
        // 请求中的授权信息
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        log.debug("授权信息：{}", authInfo);
        // 获取托管信息
        QueryWrapper<TbAction> awq = new QueryWrapper<>();
        awq.eq("mapping", authInfo.getMapping());
        awq.eq("method", authInfo.getMethod());
        TbAction action = tbActionMapper.selectOne(awq);
        log.debug("托管信息：{}", action);
        if (action == null) {
            // 不被托管的就直接通过校验
            return true;
        }
        // 获取token和对应id信息
        String token = authInfo.getToken();
        if (!StringUtils.hasText(token) || !redisService.has(token)) {
            // token不存在记录就拒绝
            return false;
        }
        Integer id = redisService.get(token, Integer.class);
        if (id == null) {
            // id信息不存在就拒绝
            return false;
        }
        // 获取用户信息
        TbUser user = tbUserMapper.selectById(id);
        log.debug("用户信息：{}", user);
        if (user == null) {
            // 用户信息不存在就拒绝
            return false;
        }
        // 获取管制信息
        QueryWrapper<TbRoleAction> rqw = new QueryWrapper<>();
        rqw.eq("role", user.getRole());
        rqw.eq("action", action.getId());
        TbRoleAction roleAction = tbRoleActionMapper.selectOne(rqw);
        log.debug("管制信息：{}", roleAction);
        return roleAction != null;
    }

    @Override
    public TbUser queryByName(String username) {
        QueryWrapper<TbUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        TbUser user = tbUserMapper.selectOne(wrapper);
        return user;
    }

    @Override
    public R<TbUser> login(UserAuth user) {
        // 校验用户是否存在
        TbUser check = queryByName(user.getUsername());
        if (check == null) {
            return R.fail("用户不存在", null);
        }
        // 校验密码，需要加密后比对
        String pwd = EncryptorUtils.saltMd5(user.getPassword(), check.getSalt());
        if (!check.getPassword().equals(pwd)) {
            return R.fail("密码错误", null);
        }
        // 登录成功需要下发token信息
        String token = UUID.randomUUID().toString();
        redisService.save(token, check.getId(), 3 * 24 * 60 * 60);
        R<TbUser> r = R.ok("登录成功", check);
        r.setToken(token);
        return r;
    }

    @Override
    public R<TbUser> queryLoginInfo() {
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        if (authInfo.getId() == null) {
            return R.fail("用户未登录", null);
        }
        TbUser user = tbUserMapper.selectById(authInfo.getId());
        if (user == null) {
            return R.fail("用户未登录", null);
        }
        return R.ok("", user);
    }

    @Override
    public R<String> logout() {
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        String token = authInfo.getToken();
        token = token == null ? "" : token;
        redisService.remove(token);
        return R.ok("退出成功", "");
    }

}
